/**
 * 
 */
package labox.innovation.gameserver.model;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javolution.util.FastList;
import labox.innovation.config.Config;
import labox.innovation.db.ConsignmentDb;
import labox.innovation.gameserver.ThreadPoolManager;
import labox.innovation.gameserver.model.ConsignmentCache.Page;
import labox.innovation.gameserver.model.ConsignmentItem.TheShelfTask;
import labox.innovation.gameserver.model.L2ItemInstance.ItemGradeType;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.itemcontainer.ConsignmentWarehouse;
import labox.innovation.gameserver.model.itemcontainer.PcInventory;
import labox.innovation.gameserver.templates.item.FuzeItemCondition;
import labox.innovation.gameserver.templates.item.L2ArmorType;
import labox.innovation.gameserver.templates.item.L2EtcItemType;
import labox.innovation.gameserver.templates.item.L2WeaponType;
import labox.innovation.gameserver.timer.Timer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ljsh
 * @description 寄售物品管理类
 */
public class ConsignmentManager {
	private static final Logger _log = LoggerFactory.getLogger(ConsignmentManager.class);
	/**
	 * 上一页
	 */
	public static final int PREVIOUSPAGE = 0;
	/**
	 * 下一页
	 */
	public static final int NEXTPAGE = 1;

	// 寄售时长分别为4,8,12,24小时
	public static final int CONSIGNMENT4 = 14400000;

	public static final int CONSIGNMENT8 = 28800000;

	public static final int CONSIGNMENT12 = 43200000;

	public static final int CONSIGNMENT24 = 86400000;

	public static final int PRICELIMIT = 2000000000;// 单价上限20亿

	/**
	 * -1,不限
	 */
	private static int _NULL = -1;

	/****** 一级类别 *******/
	/**
	 * -2,装备
	 */
	private static final int EQUIP = -2;
	/**
	 * -3.可用物品
	 */
	private static final int USEABLE = -3;
	/**
	 * -4.不可用物品
	 */
	private static final int DISABLE = -4;

	/********** 二级类别 **************/

	/**
	 * 0.武器
	 */
	private static final int WEAPON = 0;
	/**
	 * 1.头盔
	 */
	private static final int HELMET = 1;
	/**
	 * 2.项链
	 */
	private static final int NECKLACE = 3;
	/**
	 * 3.肩甲
	 */
	private static final int PAULDRON = 3;
	/**
	 * 4.胸甲
	 */
	private static final int BREASTPLATE = 4;
	/**
	 * 5.玉佩
	 */
	private static final int JADE = 5;
	/**
	 * 6.护腕
	 */
	private static final int BREACER = 6;
	/**
	 * 8.戒指
	 */
	private static final int RING = 7;
	/**
	 * 8.护腿
	 */
	private static final int PANTS = 8;
	/**
	 * 9.鞋子
	 */
	private static final int SHOE = 9;
	/**
	 * 10.法宝
	 */
	private static final int TAILSMAN = 10;

	/**
	 * 11红药
	 */
	private static final int REDPOTION = 11;
	/**
	 * 12蓝药
	 */
	private static final int BLUEPOTION = 12;
	/**
	 * 13紫药
	 */
	private static final int PURPLEPOTION = 13;
	/**
	 * 14绿药
	 */
	private static final int GREENPOTION = 14;

	/**
	 * 15洗点道具
	 */
	private static final int RETALENTS = 15;
	/**
	 * 16宝箱
	 */
	private static final int CHESTS = 16;
	/**
	 * 卷轴
	 */
	private static final int SCROLL = 17;
	/**
	 * 技能书
	 */
	private static final int SPELLBOOK = 18;
	/**
	 * 追星石
	 */
	private static final int STARSTONE = 19;
	/**
	 * 合成石
	 */
	private static final int COMPOSESTONE = 20;
	/**
	 * 打孔道具
	 */
	private static final int PUNCTURING = 21;
	/**
	 * 可镶嵌宝石
	 */
	private static final int STONECANBE = 22;
	/**
	 * 元宝
	 */
	private static final int YUANBAO = 23;
	/**
	 * 所有寄售仓库 key:charater id value:ConsignmentWarehouse
	 */
	private static Map<Long, ConsignmentWarehouse> _allConsignmentHouse = new HashMap<Long, ConsignmentWarehouse>();

	/**
	 * 所有上架物品
	 */
	private static List<ConsignmentItem> _allShelveItems = new LinkedList<ConsignmentItem>();

	/**
	 * 关于缓存用户查询条件
	 */
	private static Map<Long, ConsignmentCache> searcherCache = new HashMap<Long, ConsignmentCache>();

	/**
	 * 上架物品的所有监听者
	 */
	public static List<Long> shelveItemsListener = new LinkedList<Long>();

	public static ConsignmentCache getSearcheCache(Long uid) {
		ConsignmentCache cache = searcherCache.get(uid);
		if (cache == null) {
			cache = new ConsignmentCache();
			searcherCache.put(uid, cache);
		}
		return cache;
	}

	public static void removeSearcheCondition(Long uid) {
		searcherCache.remove(uid);
	}

	public static Map<Long, ConsignmentCache> getSeacheCondition() {
		return searcherCache;
	}

	private ConsignmentManager() {
		ConsignmentDb.restoreConsignment(_allConsignmentHouse);
		ThreadPoolManager.getInstance().scheduleWithFixedDelay(new writeBackTask(), Config.CONSGNMENT_SAVE_INTERVAL * 60000, Config.CONSGNMENT_SAVE_INTERVAL * 60000);
	}

	public static boolean addConsignmentWarehouse(ConsignmentWarehouse warehouse) {
		if (_allConsignmentHouse.containsKey(warehouse.getOwnerId()))
			return false;
		return _allConsignmentHouse.put(warehouse.getOwnerId(), warehouse) != null;
	}

	public static boolean removeConsignmentWarehouse(ConsignmentWarehouse warehouse) {
		if (!_allConsignmentHouse.containsKey(warehouse.getOwnerId()))
			return false;
		return _allConsignmentHouse.remove(warehouse.getOwnerId()) != null;
	}

	public static ConsignmentManager getInstance() {
		return Singleton._instance;
	}

	/**
	 * @param playerId
	 * @return 获取觉得的寄售仓库（只读）
	 */
	public static ConsignmentWarehouse getConsignmentWarehouse(long playerId) {
		return _allConsignmentHouse.get(playerId);
	}

	/**
	 * @param item
	 * @return 上架
	 */
	public static boolean shelve(ConsignmentItem item) {
		return _allShelveItems.add(item);
	}

	/**
	 * @param item
	 * @return 下架
	 */
	public static synchronized boolean shelf(ConsignmentItem item) {

		if (!_allShelveItems.contains(item) || item == null) {
			return false;
		}
		int index = _allShelveItems.indexOf(item);
		boolean rs = _allShelveItems.remove(item);
		if (rs) {
			StringBuilder builder = new StringBuilder();
			_log.info(builder.append("物品下架:").append(item.getItem().getName()).append("(").append(item.getItem().getObjectId()).append("),").append(item.getItem().getCount()).append("从").append(item.getItem().getOwnerId()).append("的寄售仓库下架").toString(), item.getItem().getObjectId(), item.getItem().getName());
			_log.info(builder.append("物品下架:").append(item.getItem().getName()).append("(").append(item.getItem().getObjectId()).append("),").append(item.getItem().getCount()).append("从").append(item.getItem().getOwnerId()).append("的寄售仓库下架").toString(), item.getItem().getOwnerId(), item.getItem().getOwnerId());
			updateListenerItemIndex(index);
		}
		return rs;
	}

	private static class Singleton {
		public static final ConsignmentManager _instance = new ConsignmentManager();
	}

	/**
	 * @param objectId
	 * @return 获取指定id物品
	 */
	public static ConsignmentItem getConsignmentItem(long objectId) {
		ConsignmentItem item = null;
		for (ConsignmentItem temp : _allShelveItems) {
			if (temp.getItemId() == objectId) {
				item = temp;
				break;
			}

		}
		return item;
	}

	public static List<ConsignmentItem> getAllShelveItems() {
		return _allShelveItems;
	}

	/**
	 * @param _consignmentLength
	 * @param _price
	 * @return 计算手续费
	 */
	public static int calculateHandleFee(int _consignmentLength, int _price) {
		int _handlingFee = -1;
		if(_price<0){
			return _handlingFee;
		}
		if (_consignmentLength == 4) {
			_handlingFee = (int) (_price * Config.XX4);
		} else if (_consignmentLength == 8) {
			_handlingFee = (int) (_price * Config.XX8);
		} else if (_consignmentLength == 12) {
			_handlingFee = (int) (_price * Config.XX12);
		} else if (_consignmentLength == 24) {
			_handlingFee = (int) (_price * Config.XX24);
		}
		return _handlingFee;
	}

	/**
	 * 计算购买寄售物品所需的手续费
	 * @param _price
	 * @return 
	 */
	public static int calculateBuyConsignmentHandleFee(int price) {
		return (int) (price * Config.CONSIGNMENTDUTY);
	}

	/**
	 * @return 根据物品类别查找物品
	 */
	public static List<ConsignmentItem> searchByCategory(int type, Long uid) {
		FastList<ConsignmentItem> items = new FastList<ConsignmentItem>();
		List<ConsignmentItem> allshelves = ConsignmentManager.getAllShelveItems();
		ConsignmentCache cc = getSearcheCache(uid);
		boolean isLast = false;// 是否为容器中最后一条记录
		boolean isFull = false;// 存放搜索结果的容器是否已满
		Page page = null;
		int startIndex = 0;
		int shelveSize = allshelves.size();// 所有上架物品数量
		int currentPage = cc.getCurrentPage();
		if (currentPage > 1) {
			startIndex = cc.getPageData().get(currentPage - 1).endIndex + 1;
			page = new Page(startIndex, startIndex);
		} else {
			page = cc.getPageData().get(1);
		}
		for (int i = startIndex; i < shelveSize; i++) {
			try {
				ConsignmentItem _item = allshelves.get(i);
				L2ItemInstance item = _item.getItem();
				if (type == YUANBAO && item.getItem().getItemId() == PcInventory.MONEY_YAUNBAO_ID)// 搜索元宝
				{
					isFull = addItem(items, _item);
				}
				if (type == WEAPON && item.getItemType() instanceof L2WeaponType) {
					isFull = addItem(items, _item);
				}
				if (type == HELMET && item.getItemType() == L2ArmorType.HELMET) {
					isFull = addItem(items, _item);
				}
				if (type == NECKLACE && item.getItemType() == L2ArmorType.NECKLACE) {
					isFull = addItem(items, _item);
				}
				if (type == PAULDRON && item.getItemType() == L2ArmorType.PAULDRON) {
					isFull = addItem(items, _item);
				}
				if (type == BREASTPLATE && item.getItemType() == L2ArmorType.BREASTPLATE) {
					isFull = addItem(items, _item);
				}
				if (type == JADE && item.getItemType() == L2ArmorType.JADE) {
					isFull = addItem(items, _item);
				}
				if (type == BREACER && item.getItemType() == L2ArmorType.BREACER) {
					isFull = addItem(items, _item);
				}
				if (type == RING && item.getItemType() == L2ArmorType.RING) {
					isFull = addItem(items, _item);
				}
				if (type == PANTS && item.getItemType() == L2ArmorType.PANTS) {
					isFull = addItem(items, _item);
				}
				if (type == SHOE && item.getItemType() == L2ArmorType.SHOE) {
					isFull = addItem(items, _item);
				}
				if (type == TAILSMAN && item.getItemType() == L2ArmorType.TAILSMAN) {
					isFull = addItem(items, _item);
				}
				if (type == USEABLE && item.getItemType() instanceof L2EtcItemType && item.getItemType() != L2EtcItemType.COMPOSESTONE && item.getItemType() != L2EtcItemType.STARSTONE) {
					isFull = addItem(items, _item);
				}
				if (type == DISABLE && (item.getItemType() == L2EtcItemType.COMPOSESTONE || item.getItemType() == L2EtcItemType.STARSTONE)) {
					isFull = addItem(items, _item);
				}
				if (i == shelveSize - 1) {
					isLast = true;
				}
				if (isFull) {
					break;// 当列表已满时，跳出循环
				}
			} catch (Exception e) {
				break;// 发生异常时，跳出循环，可能发生越界异常
			}
		}
		if (!items.isEmpty()) {
			page.startIndex = getConsigmentIndex(items.getFirst());
			page.endIndex = getConsigmentIndex(items.getLast());
		}
		if (isLast) {
			cc.setLastPage(true);
		}
		cc.getPageData().put(currentPage, page);
		if (items.isEmpty() && currentPage > 1) {
			cc.setCurrentPage(currentPage - 1);
		}
		return items;
	}

	/**
	 * @param firstGrade 一级类别 0,装备,1, 可用，2，不可用
	 * @param sencondGrade 二级类别
	 * @param profession 职业限制
	 * @param starLevele 追星等级
	 * @param itemQuality 物品品质
	 * @param itemLevel 等级
	 * @param priceType 价格类型
	 * @return 高级查找
	 */
	public static List<ConsignmentItem> searchByHigh(int firstGrade, int sencondGrade, int profession, int starLevele, int itemQuality, int itemLevel, int priceType, Long uid) {
		FastList<ConsignmentItem> result = new FastList<ConsignmentItem>();
		List<ConsignmentItem> allshelves = ConsignmentManager.getAllShelveItems();
		ConsignmentCache cc = getSearcheCache(uid);
		boolean isLast = false;// 是否为容器中最后一条记录
		Page page = null;
		int startIndex = 0;
		int shelveSize = allshelves.size();// 所有上架物品数量
		int currentPage = cc.getCurrentPage();
		if (currentPage > 1) {
			startIndex = cc.getPageData().get(currentPage - 1).endIndex + 1;
			page = new Page(startIndex, startIndex);
		} else {
			page = cc.getPageData().get(1);
		}
		for (int i = startIndex; i < shelveSize; i++) {
			try {
				ConsignmentItem item = allshelves.get(i);
				L2ItemInstance _item = item.getItem();
				// 判断一级类别
				if (firstGrade == EQUIP && !(_item.getItemType() instanceof L2ArmorType) && !(_item.getItemType() instanceof L2WeaponType)) {
					continue;
				} else if (firstGrade == USEABLE && (!(_item.getItemType() instanceof L2EtcItemType) || _item.getItemType() == L2EtcItemType.COMPOSESTONE || _item.getItemType() == L2EtcItemType.STARSTONE)) {
					continue;
				} else if (firstGrade == DISABLE && _item.getItemType() != L2EtcItemType.COMPOSESTONE && _item.getItemType() != L2EtcItemType.STARSTONE) {
					continue;
				}

				// 判断二级类别
				/*-------------------------------------------------------------------------*/
				// 装备
				if (sencondGrade == WEAPON && !(_item.getItemType() instanceof L2WeaponType)) {
					continue;
				}
				if (sencondGrade == HELMET && !(_item.getItemType() == L2ArmorType.HELMET)) {
					continue;
				}
				if (sencondGrade == NECKLACE && !(_item.getItemType() == L2ArmorType.NECKLACE)) {
					continue;
				}
				if (sencondGrade == PAULDRON && !(_item.getItemType() == L2ArmorType.PAULDRON)) {
					continue;
				}
				if (sencondGrade == BREASTPLATE && !(_item.getItemType() == L2ArmorType.BREASTPLATE)) {
					continue;
				}
				if (sencondGrade == JADE && _item.getItemType() != L2ArmorType.JADE) {
					continue;
				}
				if (sencondGrade == BREACER && _item.getItemType() != L2ArmorType.BREACER) {
					continue;
				}
				if (sencondGrade == RING && _item.getItemType() != L2ArmorType.RING) {
					continue;
				}
				if (sencondGrade == PANTS && _item.getItemType() != L2ArmorType.PANTS) {
					continue;
				}
				if (sencondGrade == SHOE && _item.getItemType() != L2ArmorType.SHOE) {
					continue;
				}
				if (sencondGrade == TAILSMAN && _item.getItemType() != L2ArmorType.TAILSMAN) {
					continue;
				}
				/*-------------------------------------------------------------------------*/
				// 判断可用物品
				if (sencondGrade == REDPOTION && _item.getItemType() != L2EtcItemType.REDPOTION) {
					continue;
				}
				if (sencondGrade == BLUEPOTION && _item.getItemType() != L2EtcItemType.BLUEPOTION) {
					continue;
				}
				if (sencondGrade == PURPLEPOTION && _item.getItemType() != L2EtcItemType.PURPLEPOTION) {
					continue;
				}
				if (sencondGrade == GREENPOTION && _item.getItemType() != L2EtcItemType.GREENPOTION) {
					continue;
				}
				if (sencondGrade == RETALENTS && _item.getItemType() != L2EtcItemType.RETALENTS) {
					continue;
				}
				if (sencondGrade == CHESTS && _item.getItemType() != L2EtcItemType.CHESTS) {
					continue;
				}
				if (sencondGrade == SCROLL && _item.getItemType() != L2EtcItemType.SCROLL) {
					continue;
				}
				if (sencondGrade == SPELLBOOK && _item.getItemType() != L2EtcItemType.SPELLBOOK) {
					continue;
				}
				/*-------------------------------------------------------------------------*/
				// 判断不可用物品
				if (sencondGrade == STARSTONE && _item.getItemType() != L2EtcItemType.STARSTONE) {
					continue;
				}
				if (sencondGrade == COMPOSESTONE && _item.getItemType() != L2EtcItemType.COMPOSESTONE) {
					continue;
				}

				// 3.（打孔道具） 未定
				// 4.可镶嵌宝石） 未定

				/*-------------------------------------------------------------------------*/
				// 根据职业判断
				FuzeItemCondition condition = _item.getItem().getItemCondition();
				// 没有该接口
				if (condition.getClassId() != null && condition.getClassId().contains(profession)) {
					continue;
				}
				/*-------------------------------------------------------------------------*/
				// 根据追星等级判断
				if (starLevele != _NULL && _item.getStarLvl() != starLevele) {
					continue;
				}
				// 品质
				if (itemQuality != _NULL && _item.getItemGrade() != ItemGradeType.values()[itemQuality].ordinal()) {
					continue;
				}

				// 可装备人物等级
				if (itemLevel != _NULL && getItemLevel(itemLevel) != null && !checkItemLeveOk(condition, getItemLevel(itemLevel))) {
					continue;
				}
				// 价格类型
				if (priceType != _NULL && item.getPriceType() != priceType) {
					continue;
				}

				if (i == shelveSize - 1) {
					isLast = true;
				}
				if (!isFull(result)) {
					result.add(item);
				} else {
					break;// 当列表已满时，跳出循环
				}
			} catch (Exception e) {
				break;// 发生异常时，跳出循环，可能发生越界异常
			}
		}
		if (!result.isEmpty()) {
			page.startIndex = getConsigmentIndex(result.getFirst());
			page.endIndex = getConsigmentIndex(result.getLast());
		}
		if (isLast) {
			cc.setLastPage(true);
		}
		cc.getPageData().put(currentPage, page);
		if (result.isEmpty() && currentPage > 1) {
			cc.setCurrentPage(currentPage - 1);
		}
		return result;
	}

	/**
	 * @param con
	 * @param cons
	 * @return 检测物品等级是否在指定的等级区间内
	 */
	private static boolean checkItemLeveOk(FuzeItemCondition con, int[] cons) {
		boolean rs = false;
		if (con == null || cons == null) {
			rs = false;
		}
		if (con.getMaxLvl() == -1 && con.getMinLvl() == -1) {
			return true;
		}
		if (con.getMinLvl() == -1 && con.getMaxLvl() != -1 && con.getMaxLvl() >= cons[0] && con.getMaxLvl() <= cons[1]) {
			return true;
		}
		if (con.getMaxLvl() == -1 && con.getMinLvl() != -1 && con.getMinLvl() >= cons[0] && con.getMinLvl() <= cons[1]) {
			return true;
		}
		if (con.getMaxLvl() >= cons[0] && con.getMaxLvl() <= cons[1] || con.getMinLvl() >= cons[0] && con.getMinLvl() <= cons[1]) {
			rs = true;
		}
		return rs;
	}

	/**
	 * @param lev
	 * @return 获得物品等级
	 */
	private static int[] getItemLevel(int lev) {
		int[] result = null;
		switch (lev) {
		case 0:
			result = new int[] { 1, 10 };
			break;
		case 1:
			result = new int[] { 11, 20 };
			break;
		case 2:
			result = new int[] { 21, 30 };
			break;
		case 3:
			result = new int[] { 31, 40 };
			break;
		case 4:
			result = new int[] { 51, 60 };
			break;
		case 5:
			result = new int[] { 61, 70 };
			break;
		}
		return result;
	}

	/**
	 * @param coll
	 * @param item 向容器中添加物品，并返回是是否允许添加
	 */
	public static boolean addItem(List<ConsignmentItem> coll, ConsignmentItem item) {
		if (coll.size() < Config.CPAGESIZE) {
			coll.add(item);
			return false;
		} else {
			return true;
		}
	}

	private static boolean isFull(List<ConsignmentItem> collection) {
		if (collection.size() < Config.CPAGESIZE)
			return false;
		else
			return true;
	}

	/**
	 * @param uid
	 */
	public static void addShelveItemListener(Long uid) {
		if (!shelveItemsListener.contains(uid))
			shelveItemsListener.add(uid);
	}

	public static void removeShelveItemListener(Long uid) {
		if (!shelveItemsListener.contains(uid))
			shelveItemsListener.remove(uid);
	}

	/**
	 * @param start 更新物品索引
	 */
	private static void updateListenerItemIndex(int start) {
		for (Long uid : shelveItemsListener) {
			if (searcherCache.get(uid) != null) {
				int current = searcherCache.get(uid).getCurrentPage();
				if (current > 1) {
					Map<Integer, Page> data = searcherCache.get(uid).getPageData();
					for (int i = 1; i <= current; i++) {
						Page pa = data.get(i);
						if (pa == null)
							continue;
						if (pa.startIndex > start) {
							pa.startIndex -= 1;
							pa.endIndex -= 1;
						}
						if (pa.startIndex < start && pa.endIndex > start) {
							pa.endIndex -= 1;
						}
					}
				}
			}
		}
	}

	/**
	 * @param active
	 * @param item
	 * @return 检测是否可寄售物品
	 */
	public static boolean isCanShevleItems(FuzePcInstance active, L2ItemInstance item) {
		for (L2ItemInstance temp : active.getInventory().getAllConsignmentDatas()) {
			if (item == temp) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @param house 加载寄售物品
	 */
	public static void initConsignmentItem(ConsignmentWarehouse house, ConsignmentItem item) {
		house.addConsignmentItem(item);
		if (item.isShelve()) {
			if (item.getShelveTime() + item.getConsignmentLength() > System.currentTimeMillis()) {
				boolean ok = shelve(item);
				if (ok) {
					Timer timer = new Timer(item.getConsignmentLength() - (System.currentTimeMillis() - item.getShelveTime()), false, new TheShelfTask(item));
					item.setTimer(timer);
					timer.start();
				}
			} else {
				item.setShelve(false);
			}
		}

	}

	private static int getConsigmentIndex(ConsignmentItem item) {
		return getAllShelveItems().indexOf(item);
	}

	public static void reTakeMoney(FuzePcInstance player) {
		ConsignmentWarehouse conhouse = getConsignmentWarehouse(player.getObjectId());
		if (conhouse != null) {
			conhouse.reTakeMoney(player);
		}
	}

	/**
	 * @param t
	 * @return 获得寄售时长
	 */
	public static int getConsgnmentLength(int t) {
		switch (t) {
		case 4:
			return CONSIGNMENT4;

		case 8:
			return CONSIGNMENT8;

		case 12:
			return CONSIGNMENT12;

		case 24:
			return CONSIGNMENT24;

		default:
			return 0;
		}

	}

	/**
	 * 启动定时器回写寄售仓库数据
	 */
	public static void save() {
		if (_log.isDebugEnabled())
			_log.debug("寄售物品回写数据库...");
		ConsignmentDb.storeConsignment(_allConsignmentHouse);
	}

	public static class writeBackTask implements Runnable {

		@Override
		public void run() {
			if (_log.isDebugEnabled())
				_log.debug("寄售物品（线程池）回写数据库...");
			try {
				ConsignmentDb.storeConsignment(_allConsignmentHouse);
			} catch (Exception e) {
				_log.error("consignment items save thread error", Config.SERVER_ID, e);
			}

		}

	}
}
